﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace WMSNet.Core.Infrastructure.Api
{
    public class CompressedContent : HttpContent
    {
        private HttpContent originalContent;
        private string encodingType;

        public CompressedContent(HttpContent content, string encodingType)
        {
            if (content == null)
                throw new ArgumentNullException("content");
            if (encodingType == null)
                throw new ArgumentNullException("encodingType");
            this.originalContent = content;
            this.encodingType = encodingType.ToLowerInvariant();
            if (this.encodingType != "gzip" && this.encodingType != "deflate")
                throw new InvalidOperationException(string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", (object)this.encodingType));
            foreach (KeyValuePair<string, IEnumerable<string>> keyValuePair in (HttpHeaders)this.originalContent.Headers)
                this.Headers.TryAddWithoutValidation(keyValuePair.Key, keyValuePair.Value);
            this.Headers.ContentEncoding.Add(encodingType);
        }

        protected override bool TryComputeLength(out long length)
        {
            length = -1L;
            return false;
        }

        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            Stream compressedStream = (Stream)null;
            if (this.encodingType == "gzip")
                compressedStream = (Stream)new GZipStream(stream, CompressionMode.Compress, true);
            else if (this.encodingType == "deflate")
                compressedStream = (Stream)new DeflateStream(stream, CompressionMode.Compress, true);
            return this.originalContent.CopyToAsync(compressedStream).ContinueWith((Action<Task>)(tsk =>
            {
                if (compressedStream == null)
                    return;
                compressedStream.Dispose();
            }));
        }
    }
}
